package main

import (
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

/**
- 编写一个事务，实现从账户 A 向账户 B 转账 100 元的操作。
在事务中，需要先检查账户 A 的余额是否足够，
如果足够则从账户 A 扣除 100 元，向账户 B 增加 100 元，
并在 transactions 表中记录该笔转账信息。
如果余额不足，则回滚事务。
*/

type Account struct {
	gorm.Model
	Balance float64
}

type Transaction struct {
	gorm.Model
	InId  *uint
	OutId *uint
	Amt   *float64
}

func (out *Account) transfer(db *gorm.DB, in *Account, amt float64) {
	tx := db.Begin()
	if out.Balance >= 100 {
		t := &Transaction{InId: &in.ID, OutId: &out.ID}
		out.Balance = out.Balance - amt
		tx.Save(&out)
		in.Balance = in.Balance + amt
		tx.Save(&in)
		t.Amt = &amt
		tx.Create(&t)

		defer tx.Commit()
	} else {
		defer tx.Rollback()
	}

}

func main() {
	db := InitDB()

	//初始化
	db.AutoMigrate(&Account{})
	db.AutoMigrate(&Transaction{})
	db.Create(&Account{Balance: 100})
	db.Create(&Account{Balance: 200})

	//查询
	a := &Account{}
	b := &Account{}
	amt := 100.0

	db.First(&a, 1)
	db.First(&b, 2)
	a.transfer(db, b, amt)

}

func InitDB() *gorm.DB {
	db := ConnectDB()
	return db
}

func ConnectDB() *gorm.DB {
	//dsn := "user:pass@tcp(127.0.0.1:3306)/gorm?charset=utf8mb4&parseTime=True&loc=Local"
	//db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

	db, err := gorm.Open(mysql.New(mysql.Config{
		DSN:                       "root:123456@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local",
		DefaultStringSize:         256,   // string 类型字段的默认长度
		DisableDatetimePrecision:  true,  // 禁用 datetime 精度，MySQL 5.6 之前的数据库不支持
		DontSupportRenameIndex:    true,  // 重命名索引时采用删除并新建的方式，MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
		DontSupportRenameColumn:   true,  // 用 `change` 重命名列，MySQL 8 之前的数据库和 MariaDB 不支持重命名列
		SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
	}), &gorm.Config{})
	if err != nil {
		panic(err)
	}
	return db
}
